package com.xuef.security.browser;

import com.xuef.base.ApiResponse;
import com.xuef.base.Cons;
import com.xuef.entity.Catalog;
import com.xuef.entity.Role;
import com.xuef.entity.User;
import com.xuef.service.CatalogService;
import com.xuef.service.IRoleService;
import com.xuef.service.IUserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;

/**
 * Created by moveb on 2018/5/20.
 * 处理登录认证相关
 */
@Controller
public class BrowserSecurityController {

    private static final Logger logger = LoggerFactory.getLogger(BrowserSecurityController.class);
    @Autowired
    private IUserService userService;
    @Autowired
    private IRoleService roleService;
    @Autowired
    private CatalogService catalogService;
    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    protected AuthenticationManager authenticationManager;
    /**
     * 获取登录界面
     * @return
     */
    @GetMapping("/login")
    public String loginPage(){
        return "login";
    }

    /**
     * 需要登录 提醒
     * 这里应该根据请求的url来决定如何跳转
     * 目前只是统一重定向到 /login 登录页面
     * @return
     */
    @GetMapping("/authentication/require")
    public String requireLogin(){
        return "redirect:/login";
    }

    @GetMapping("/login-error")
    public String loginError(Model model) {
        model.addAttribute("loginError", true);
        model.addAttribute("errorMsg", "登录失败，账号或密码错误！");
        return "login";
    }
    @GetMapping("/logout")
    public String logout(Model model, Authentication auth,
                         HttpServletRequest request,
                         HttpServletResponse response){
        // 有可能session已经失效，那么认证也会随之失效。
        if (auth != null){
            new SecurityContextLogoutHandler().logout(request, response, auth);
        }
        //You can redirect wherever you want, but generally it's a good practice to show login screen again.
        return "redirect:/login";
    }

    /**
     * 注册时，校验用户名和邮箱是否已经存在
     * @param username
     * @param email
     * @return
     */
    @PostMapping("/check")
    public ResponseEntity<ApiResponse> check(String username, String email){
        User user = userService.findByUsername(username);
        User userByEmail = userService.findByEmail(email);
        if(user != null || userByEmail != null){
            return ResponseEntity.ok().body(ApiResponse.ofMessage(20000, "账号或邮箱已存在"));
        }
        return ResponseEntity.ok().body(ApiResponse.ofSuccess("账号邮箱可用"));
    }

    /**
     * 获取注册页面
     * @return
     */
    @GetMapping("/register")
    public String register() {
        return "register";
    }

    /**
     * 用户注册
     * @param user
     * @return
     */
    @PostMapping("/register")
    public String registerUser(User user, HttpServletRequest request) {
        List<Role> authorities = new ArrayList<>();

        /**
         * 默认USER 角色
         */
        Role role = new Role();
        role.setName(Cons.ROLE.USER.getRoleName());

        authorities.add(role);
        // 原始密码
        String rawPwd = user.getPassword();
        user.setAuthorities(authorities);
        user.setPassword(passwordEncoder.encode(user.getPassword())); // 加密密码
        // 默认头像
        user.setHeadUrl(Cons.DEFAULT_AVATAR);
        // 前端注册时，未要求email TODO
        if(user.getEmail() == null) {
            user.setEmail("...@xxx.com");
        }
        user = userService.saveUser(user);

        role.setUserId(user.getId());
        roleService.save(role);
        // 分配一个home目录
        Catalog c = new Catalog(user, "home");
        c.setUserId(user.getId());
        c.setCreateTime(new Date());
        catalogService.saveCatalog(c);
        // 自动登录，前往用户主页
        //进行授权登录
        UsernamePasswordAuthenticationToken token = new
                UsernamePasswordAuthenticationToken(user.getUsername(), rawPwd);
        try{
            token.setDetails(new WebAuthenticationDetails(request));
            Authentication authenticatedUser = authenticationManager.authenticate(token);
            SecurityContextHolder.getContext().setAuthentication(authenticatedUser);
            request.getSession().setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, SecurityContextHolder.getContext());
        } catch( AuthenticationException e ){
            logger.error("Authentication failed: " + e.getMessage());
            return "redirect:/register";
        }
        // 跳到首页
        //return "redirect:/";
        // 跳到用户主页
        return "redirect:/space/"+user.getUsername();
    }

    @GetMapping("/search")
    public String search() {
        return "search";
    }
}
